package com.googlecode.contests_repo.servlets;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;

import com.googlecode.contests_repo.core.WebTools;
import com.googlecode.contests_repo.core.model.*;
import com.googlecode.contests_repo.validation.ValidationTools;

/**
 * Servlet implementation class ProblemEditServlet
 */
@WebServlet("/ProblemEditServlet")
public class ProblemEditServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		List<String> errors = new ArrayList<String>();
		String relativeProblemPath = request.getParameter("path");
		Problem oldProblem = getOldFieldData(request);
		Problem newProblem = getNewFieldData(request, errors);
		Problem currentProblem = getCurrentResource(relativeProblemPath);

            	currentProblem.setTitle(newProblem.getTitle());
            	currentProblem.setAbout(newProblem.getAbout());
            	currentProblem.setNotes(newProblem.getNotes());
            	currentProblem.setOrigin(newProblem.getOrigin());
		
		
		if (newProblem.getTimeLimit() < 0) {
			errors.add(WebTools.getFormatMessage("red",
					"Entered time limit is invalid"));
		} else if (oldProblem.getTimeLimit() != newProblem.getTimeLimit()) {
			currentProblem.setTimeLimit(newProblem.getTimeLimit());
		}
		if (newProblem.getMemoryLimit() < 0) {
			errors.add(WebTools.getFormatMessage("red",
					"Entered memory limit is invalid"));
		} else if (oldProblem.getMemoryLimit() != newProblem.getMemoryLimit()) {
			currentProblem.setMemoryLimit(newProblem.getMemoryLimit());
		}
		if (newProblem.getAuthors() != null
				&& !Arrays.equals(oldProblem.getAuthors(),
					newProblem.getAuthors())) {
			currentProblem.setAuthors(newProblem.getAuthors());
		}
		if (newProblem.getTestWeights() != null
        			&& !Arrays.equals(oldProblem.getTestWeights(),
        				newProblem.getTestWeights())) {
        		currentProblem.setTestWeights(newProblem.getTestWeights());
        	}


		// validate
		errors.addAll(ValidationTools.validate(relativeProblemPath, Problem.class));

		// save problem.json file
		ObjectMapper mapper = new ObjectMapper();
		String fullProblemPath = ResourcesUtils
				.getFullResourcePath(relativeProblemPath);
		try {
			mapper.writeValue(new File(fullProblemPath, "problem.json"),
					currentProblem);
		} catch (Exception e) {
			errors.add(e.getMessage());
		}

		// send response
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println(WebTools.buildErrorString(errors, true));
	}

	private Problem getNewFieldData(HttpServletRequest request,
			List<String> errors) {
		Problem problem = new Problem();
		problem.setAbout(request.getParameter("about"));
		problem.setChecker(request.getParameter("checker"));
		problem.setId(request.getParameter("id"));
		problem.setNotes(request.getParameter("notes"));
		problem.setTitle(request.getParameter("title"));
		problem.setOrigin(request.getParameter("origin"));
		
		int memoryLimit = -1;
		try {
			memoryLimit = Integer.parseInt(request.getParameter("memory-limit"));
		} catch (Exception e) {		}
		problem.setMemoryLimit(memoryLimit);

		double timeLimit = -1;
		try {
		    timeLimit = Double.parseDouble(request.getParameter("time-limit"));
		} catch (Exception e) {		}
		problem.setTimeLimit(timeLimit);

		
		String[] authors = WebTools.stringToArray(request
				.getParameter("authors"));
		if (authors == null) {
			authors = new String[] {};
		}
		problem.setAuthors(authors);
		
		
		int[] testWeights = null;
		try {
			testWeights = WebTools.integerStringToArray(request
					.getParameter("test-weights"));
			if (testWeights == null) {
				testWeights = new int[] {};
			}
		} catch (Exception e) {
			if (errors != null) {
				errors.add("Test weights cannot be parsed: " + e.getMessage());
			}
		}
		problem.setTestWeights(testWeights);

		return problem;
	}

	private Problem getOldFieldData(HttpServletRequest request) {
		Problem problem = new Problem();
		problem.setAbout(request.getParameter("old-about"));
		problem.setChecker(request.getParameter("old-checker"));
		problem.setId(request.getParameter("old-id"));
		problem.setNotes(request.getParameter("old-notes"));
		problem.setTitle(request.getParameter("old-title"));
		problem.setOrigin(request.getParameter("old-origin"));
		
		int memoryLimit = -1;
		try {
			memoryLimit = Integer.parseInt(request.getParameter("old-memory-limit"));
		} catch (Exception e) {		}
		problem.setMemoryLimit(memoryLimit);

		double timeLimit = -1;
		try {
		    timeLimit = Double.parseDouble(request.getParameter("old-time-limit"));
		} catch (Exception e) {		}
		problem.setTimeLimit(timeLimit);

		
		String[] authors = WebTools.stringToArray(request
				.getParameter("old-authors"));
		if (authors == null) {
			authors = new String[] {};
		}
		problem.setAuthors(authors);
		
		
		int[] testWeights = null;
		try {
			testWeights = WebTools.integerStringToArray(request
					.getParameter("old-test-weights"));
			if (testWeights == null) {
				testWeights = new int[] {};
			}
		} catch (Exception e) {
			
		}
		problem.setTestWeights(testWeights);

		return problem;
	}

	private Problem getCurrentResource(String relativeResourcePath) {
		String resourcePath = ResourcesUtils
				.getFullResourcePath(relativeResourcePath);

		return ResourcesUtils.getJSON(new File(resourcePath));
	}
}
